Do you know about Philosophy? If you read a lot about them, that’s very cool. Hope you find this article helpful from the perspective of data analysis and visualization. If you are not very familiar with this subject (just as I am), don’t worry. You will get the first impression on each main school of Philosophy.

The first part of the data story is about analysis of the whole corpus of Philosophy. It will bring you an overview of the data set we are currently working on. The second part focuses on sentiment analysis of two interesting schools: Capitalism and Communism.

Part 1: Data set overview. Let’s look at the whole curpus!

Setting up environment

This report is prepared with the following environmental settings.

print(R.version)
               _                           
platform       x86_64-apple-darwin17.0     
arch           x86_64                      
os             darwin17.0                  
system         x86_64, darwin17.0          
status                                     
major          4                           
minor          0.3                         
year           2020                        
month          10                          
day            10                          
svn rev        79318                       
language       R                           
version.string R version 4.0.3 (2020-10-10)
nickname       Bunny-Wunnies Freak Out     

Load the packages and source files

We don’t need all the packages listed there. They covers the functionality from generating, cleaning the original data set, to data analysis, manipulation, visualization, and sentiment analysis etc.. We mainly focus on the latter part of the functions.

I wrote two functions f.clean.corpus and f.make.tdm in the ../lib/wordcloudFuncs.R since we would generate many word clouds using these wrapped functions rather than writing similar, redundant code.

packages.used=c("rvest", "tibble", 
                "sentimentr", "gplots", "dplyr",
                "tm", "syuzhet", "factoextra", 
                "beeswarm", "scales", "RColorBrewer",
                "RANN", "topicmodels", "stringr", 
                "ggridges", "wordcloud", "wordcloud2",
                "tidytext", "knitr", "tidyverse")
# check packages that need to be installed.
packages.needed=setdiff(packages.used, 
                        intersect(installed.packages()[,1], 
                                  packages.used))
# install additional packages
if(length(packages.needed)>0){
  install.packages(packages.needed, dependencies = TRUE)
}
# load packages
library("rvest")
library("tibble")
library("syuzhet")
library("sentimentr")
library("gplots")
library("dplyr")
library("tm")
library("syuzhet")
library("factoextra")
library("beeswarm")
library("scales")
library("RColorBrewer")
library("RANN")
library("tm")
library("topicmodels")
library("stringr")
library("ggplot2")
#library("ggridges")
#library("viridis")
library("wordcloud")
library("wordcloud2")
library("tidytext")
library("knitr")
library("tidyverse")

#source("../lib/plotstacked.R")
source("../lib/speechFuncs.R")
source("../lib/wordcloudFuncs.R")

Load the dataset

The data set ../data/philosophy_data.csv contains 360808 sentences taken from 51 texts spanning the history of philosophy. You can find more details about it in https://www.kaggle.com/kouroshalizadeh/history-of-philosophy.

file<-'../data/philosophy_data.csv'
full_data <- read.csv(file)
full_data <- full_data %>% 
  mutate(word.count = f.word_count(sentence_spacy))
# sentence.list is generated from the chunk {r generate sentence.list}. This will 
# cost 25-30 minutes. To save your time, you can simply use it.
# Feel free if you don't want to run {r generate sentence.list}
subfile <- '../output/sentence.list.csv'
sentence.list <- read.csv(subfile)

reduced_data = full_data %>% select(title, author, school, sentence_spacy, original_publication_date, sentence_length, word.count)

#trial_data <- reduced_data[1:1000,]
data <- reduced_data %>% filter(school == "capitalism" | school == "communism")

Step : Length of sentences of different schools?

data.byschool <- reduced_data %>% group_by(school) %>%
  summarise(meanlength = mean(word.count)) %>%
  arrange(meanlength)
  
g1 <- data.byschool %>% ggplot(aes(x = reorder(school, meanlength), y = meanlength, fill = school)) + 
  geom_bar(stat = "identity") +
  labs(
    title = "Bar plot: mean length of sentences(word count) of different schools",
    x = "Schools",
    y = "Mean Length of Sentences"
  ) +
  coord_flip()

g1

In addition to the mean length of sentences, this plot will show more details of actual distributon of sentence length.

data.byschool <- reduced_data %>% group_by(school) 
g2 <- data.byschool %>% ggplot(aes(x = school, y = word.count, fill = school)) +
  geom_violin(alpha = 0.5) +
  #geom_point(position = position_jitter(seed = 1, width = 0.2)) +
  theme(legend.position = "none") +
  geom_boxplot(width=.1) +
  labs(
    title = "violin plot + box plot: spread of sentences' length \n of different schools",
    x = "Schools",
    y = "Length of Sentences"
  ) +
  coord_flip()

g2

Step 1: What are the frequently mentioned words?

Let’s have an overview of frequency of words in the whole corpus.

Now let’s see the word clouds of different schools.

Capitalism:

Empiricism:

German_idealism:

Continental:

Rationalism:

Aristotle:

Feminism:

Communism:

Phenomenology:

stoicism:

Analytic:

Nietzsche:

Plato:

Step : sentiment analysis on Capitalism and Communism

names(sentence.list)
 [1] "X.1"                       "X"                         "title"                    
 [4] "author"                    "school"                    "sentence_spacy"           
 [7] "original_publication_date" "sentence_length"           "sentences"                
[10] "anger"                     "anticipation"              "disgust"                  
[13] "fear"                      "joy"                       "sadness"                  
[16] "surprise"                  "trust"                     "negative"                 
[19] "positive"                  "sent.id"                   "word.count"               

Emotionally charged sentences

Capitalism:

emotions.types=c("anticipation", "joy", "surprise", "trust",
                 "anger", "disgust", "fear", "sadness", "negative", "positive")

speech.df=tbl_df(sentence.list) %>%
  filter(school == "capitalism", word.count < 20) %>%
  select(sentences, anger:positive)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
 [1] "This complaint, however, of the scarcity of money, is not always confined to improvident spendthrifts."                                        
 [2] "This money, however, was for a long time, received at the exchequer, by weight, and not by tale."                                              
 [3] "Bankruptcy is, perhaps, the greatest and most humiliating calamity which can befal an innocent man."                                           
 [4] "Poverty, though it no doubt discourages, does not always prevent, marriage."                                                                   
 [5] "The cheapness and plenty of good land encourage improvement, and enable the proprietor to pay those high wages."                               
 [6] "below its standard weight, the bank would, in this case, have lost only one percent."                                                          
 [7] "Its nominal price was a good deal lower than at present."                                                                                      
 [8] "The cheapness and plenty of good land encourage improvement, and enable the proprietor to pay those high wages."                               
 [9] "Not only ignorance and misinformation, but friendship, party animosity, and private resentment, are said frequently to mislead such assessors."
[10] "The cheapness and plenty of good land encourage improvement, and enable the proprietor to pay those high wages."                               

Communism:


speech.df=tbl_df(sentence.list) %>%
  filter(school == "communism", word.count < 20) %>%
  select(sentences, anger:positive)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
 [1] "In actual history it is notorious that conquest, enslavement, robbery, murder, briefly force, play the great part."        
 [2] "The new nobility was the child of its time, for which money was the power of all powers."                                  
 [3] "Or perhaps Bastiat means, that a mode of production based on slavery is based on a system of plunder."                     
 [4] "In actual history it is notorious that conquest, enslavement, robbery, murder, briefly force, play the great part."        
 [5] "the rich grow rapidly richer, whilst there is no perceptible advance in the comfort enjoyed by the industrial classes."    
 [6] "One old woman was burnt to death in the flames of the hut, which she refused to leave."                                    
 [7] "Then one use value is just as good as another, provided only it be present in sufficient quantity."                        
 [8] "Dr. Simon, medical officer to the Privy Council, chose for this work the above mentioned Dr. Smith."                       
 [9] "In actual history it is notorious that conquest, enslavement, robbery, murder, briefly force, play the great part."        
[10] "In order to be fully prepared for his task, the working class revolutionary must also become a professional revolutionary."

Clustering of emotions

Capitalism:

heatmap.2(cor(sentence.list%>%filter(school=="capitalism")%>%select(anger:positive)), 
          scale = "none", 
          col = bluered(100), , margin=c(6, 6), key=F,
          trace = "none", density.info = "none")
par(mar=c(4, 6, 2, 1))

Communism:

heatmap.2(cor(sentence.list%>%filter(school=="communism")%>%select(anger:positive)), 
          scale = "none", 
          col = bluered(100), , margin=c(6, 6), key=F,
          trace = "none", density.info = "none")
par(mar=c(4, 6, 2, 1))

sentence.list.capitalism <- sentence.list %>% filter(school=="capitalism")
emo.means1=colMeans(select(sentence.list.capitalism, anger:positive)>0.01)
col.use1=c("red2", "darkgoldenrod1", "chartreuse3","blueviolet", "darkgoldenrod1", "dodgerblue3", "darkgoldenrod1", "darkgoldenrod1", "black", "darkgoldenrod1")
barplot(emo.means1[order(emo.means1)], las=2, col=col.use1[order(emo.means1)], horiz=T,
        cex.names=0.7, main="Capitalism")

sentiment.df1 <- data.frame(
  group=c("anger", "anticipation", "disgust","fear", "joy", "sadness", "surprise", "trust", "negative", "positive"),
  value=emo.means1
)

sentiment.df1 <- sentiment.df1 %>% 
  mutate(perc = value / sum(value)) %>% 
  arrange(perc) %>%
  mutate(labels = scales::percent(perc))


ggplot(sentiment.df1, aes(x="", y=perc, fill=group)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  geom_text(aes(label = labels), 
            position = position_stack(vjust = 0.5),
            show.legend = FALSE,
            color = "white", size=3) +
  scale_fill_brewer(palette="Spectral") +
  labs(
    title = "Percentage of the sentiment in Capitalism",
    x = "",
    y = "",
  )

sentence.list.communism <- sentence.list %>% filter(school=="communism")
emo.means2=colMeans(select(sentence.list.communism, anger:positive)>0.01)
col.use2=c("red2", "darkgoldenrod1", "chartreuse3","blueviolet", "darkgoldenrod1", "dodgerblue3", "darkgoldenrod1", "darkgoldenrod1", "black", "darkgoldenrod1")
barplot(emo.means2[order(emo.means2)], las=2, col=col.use2[order(emo.means2)], horiz=T,
        cex.names=0.7, main="Communism")

sentiment.df2 <- data.frame(
  group=c("anger", "anticipation", "disgust","fear", "joy", "sadness", "surprise", "trust", "negative", "positive"),
  value=emo.means2
)

sentiment.df2 <- sentiment.df2 %>% 
  mutate(perc = value / sum(value)) %>% 
  arrange(perc) %>%
  mutate(labels = scales::percent(perc))


ggplot(sentiment.df2, aes(x="", y=perc, fill=group)) +
  geom_bar(stat="identity", width=1, color="white") +
  coord_polar("y", start=0) +
  geom_text(aes(label = labels), 
            position = position_stack(vjust = 0.5),
            show.legend = FALSE,
            color = "white", size=3) +
  scale_fill_brewer(palette="Spectral") +
  labs(
    title = "Percentage of the sentiment in Communism",
    x = "",
    y = "",
  )

sentiment.df.all <- data.frame(
  group=c("anger", "anticipation", "disgust","fear", "joy", "sadness", "surprise", "trust", "negative", "positive"),
  capitalism=emo.means1,
  communism=emo.means2
)

sentiment.df.all.long <- sentiment.df.all %>% pivot_longer(c("capitalism", "communism"))

g3 <- sentiment.df.all.long %>% ggplot(aes(x = group, y = value, fill = name)) +
  geom_col(position = "dodge") +
  labs(
    x = "",
    y = "mean score of sentiment",
    title = "Sentiment comparison: Capitalism vs. Communism"
  )

g3

sentence.list.Marx <- sentence.list %>% filter(author=="Marx")
emo.means.Marx=colMeans(select(sentence.list.Marx, anger:positive)>0.01)

sentence.list.Lenin <- sentence.list %>% filter(author=="Lenin")
emo.means.Lenin=colMeans(select(sentence.list.Lenin, anger:positive)>0.01)

sentence.list.Smith <- sentence.list %>% filter(author=="Smith")
emo.means.Smith=colMeans(select(sentence.list.Smith, anger:positive)>0.01)

sentence.list.Ricardo <- sentence.list %>% filter(author=="Ricardo")
emo.means.Ricardo=colMeans(select(sentence.list.Ricardo, anger:positive)>0.01)

sentence.list.Keynes <- sentence.list %>% filter(author=="Keynes")
emo.means.Keynes=colMeans(select(sentence.list.Keynes, anger:positive)>0.01)

sentiment.df.byauthor <- data.frame(
  group=c("anger", "anticipation", "disgust","fear", "joy", "sadness", "surprise", "trust", "negative", "positive"),
  Marx=emo.means.Marx,
  Lenin=emo.means.Lenin,
  Smith=emo.means.Smith,
  Ricardo=emo.means.Ricardo,
  Keynes=emo.means.Keynes
)

sentiment.df.byauthor.long <- sentiment.df.byauthor %>% pivot_longer(c("Marx", "Lenin", "Smith", "Ricardo", "Keynes" ))

g4 <- sentiment.df.byauthor.long %>% ggplot(aes(x = group, y = value, fill = name)) +
  geom_col(position = "dodge") +
  labs(
    x = "",
    y = "mean score of sentiment",
    title = "Sentiment comparison: all the authors",
    subtitle = "Communism: Marx, Lenin \nCapitalism: Keynes, Ricardo, Smith"
  )

g4

LS0tCnRpdGxlOiAiSW52ZXN0aWdhdGluZyBkaWZmZXJlbnQgc2Nob29scyBvZiBQaGlsb3NvcGh5LS1DYXBpdGFsaXNtIHZzLiBDb21tdW5pc20iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkRvIHlvdSBrbm93IGFib3V0IFBoaWxvc29waHk/IElmIHlvdSByZWFkIGEgbG90IGFib3V0IHRoZW0sIHRoYXQncyB2ZXJ5IGNvb2wuIEhvcGUgeW91IGZpbmQgdGhpcyBhcnRpY2xlIGhlbHBmdWwgZnJvbSB0aGUgcGVyc3BlY3RpdmUgb2YgZGF0YSBhbmFseXNpcyBhbmQgdmlzdWFsaXphdGlvbi4gSWYgeW91IGFyZSBub3QgdmVyeSBmYW1pbGlhciB3aXRoIHRoaXMgc3ViamVjdCAoanVzdCBhcyBJIGFtKSwgZG9uJ3Qgd29ycnkuIFlvdSB3aWxsIGdldCB0aGUgZmlyc3QgaW1wcmVzc2lvbiBvbiBlYWNoIG1haW4gc2Nob29sIG9mIFBoaWxvc29waHkuIAoKVGhlIGZpcnN0IHBhcnQgb2YgdGhlIGRhdGEgc3RvcnkgaXMgYWJvdXQgYW5hbHlzaXMgb2YgdGhlIHdob2xlIGNvcnB1cyBvZiBQaGlsb3NvcGh5LiBJdCB3aWxsIGJyaW5nIHlvdSBhbiBvdmVydmlldyBvZiB0aGUgZGF0YSBzZXQgd2UgYXJlIGN1cnJlbnRseSB3b3JraW5nIG9uLiBUaGUgc2Vjb25kIHBhcnQgZm9jdXNlcyBvbiBzZW50aW1lbnQgYW5hbHlzaXMgb2YgdHdvIGludGVyZXN0aW5nIHNjaG9vbHM6IENhcGl0YWxpc20gYW5kIENvbW11bmlzbS4gCgojIFBhcnQgMTogRGF0YSBzZXQgb3ZlcnZpZXcuIExldCdzIGxvb2sgYXQgdGhlIHdob2xlIGN1cnB1cyEKCiMjIFNldHRpbmcgdXAgZW52aXJvbm1lbnQKCmBgYHtyIHNldHVwLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgpUaGlzIHJlcG9ydCBpcyBwcmVwYXJlZCB3aXRoIHRoZSBmb2xsb3dpbmcgZW52aXJvbm1lbnRhbCBzZXR0aW5ncy4KCmBgYHtyfQpwcmludChSLnZlcnNpb24pCmBgYAoKIyMgTG9hZCB0aGUgcGFja2FnZXMgYW5kIHNvdXJjZSBmaWxlcwpXZSBkb24ndCBuZWVkIGFsbCB0aGUgcGFja2FnZXMgbGlzdGVkIHRoZXJlLiBUaGV5IGNvdmVycyB0aGUgZnVuY3Rpb25hbGl0eSBmcm9tIGdlbmVyYXRpbmcsIGNsZWFuaW5nIHRoZSBvcmlnaW5hbCBkYXRhIHNldCwgdG8gZGF0YSBhbmFseXNpcywgbWFuaXB1bGF0aW9uLCB2aXN1YWxpemF0aW9uLCBhbmQgc2VudGltZW50IGFuYWx5c2lzIGV0Yy4uIFdlIG1haW5seSBmb2N1cyBvbiB0aGUgbGF0dGVyIHBhcnQgb2YgdGhlIGZ1bmN0aW9ucy4KCkkgd3JvdGUgdHdvIGZ1bmN0aW9ucyAqKmYuY2xlYW4uY29ycHVzKiogYW5kICoqZi5tYWtlLnRkbSoqIGluIHRoZSAqLi4vbGliL3dvcmRjbG91ZEZ1bmNzLlIqIHNpbmNlIHdlIHdvdWxkIGdlbmVyYXRlIG1hbnkgd29yZCBjbG91ZHMgdXNpbmcgdGhlc2Ugd3JhcHBlZCBmdW5jdGlvbnMgcmF0aGVyIHRoYW4gd3JpdGluZyBzaW1pbGFyLCByZWR1bmRhbnQgY29kZS4gCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGFja2FnZXMudXNlZD1jKCJydmVzdCIsICJ0aWJibGUiLCAKICAgICAgICAgICAgICAgICJzZW50aW1lbnRyIiwgImdwbG90cyIsICJkcGx5ciIsCiAgICAgICAgICAgICAgICAidG0iLCAic3l1emhldCIsICJmYWN0b2V4dHJhIiwgCiAgICAgICAgICAgICAgICAiYmVlc3dhcm0iLCAic2NhbGVzIiwgIlJDb2xvckJyZXdlciIsCiAgICAgICAgICAgICAgICAiUkFOTiIsICJ0b3BpY21vZGVscyIsICJzdHJpbmdyIiwgCiAgICAgICAgICAgICAgICAiZ2dyaWRnZXMiLCAid29yZGNsb3VkIiwgIndvcmRjbG91ZDIiLAogICAgICAgICAgICAgICAgInRpZHl0ZXh0IiwgImtuaXRyIiwgInRpZHl2ZXJzZSIpCiMgY2hlY2sgcGFja2FnZXMgdGhhdCBuZWVkIHRvIGJlIGluc3RhbGxlZC4KcGFja2FnZXMubmVlZGVkPXNldGRpZmYocGFja2FnZXMudXNlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGludGVyc2VjdChpbnN0YWxsZWQucGFja2FnZXMoKVssMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2FnZXMudXNlZCkpCiMgaW5zdGFsbCBhZGRpdGlvbmFsIHBhY2thZ2VzCmlmKGxlbmd0aChwYWNrYWdlcy5uZWVkZWQpPjApewogIGluc3RhbGwucGFja2FnZXMocGFja2FnZXMubmVlZGVkLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQp9CiMgbG9hZCBwYWNrYWdlcwpsaWJyYXJ5KCJydmVzdCIpCmxpYnJhcnkoInRpYmJsZSIpCmxpYnJhcnkoInN5dXpoZXQiKQpsaWJyYXJ5KCJzZW50aW1lbnRyIikKbGlicmFyeSgiZ3Bsb3RzIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJ0bSIpCmxpYnJhcnkoInN5dXpoZXQiKQpsaWJyYXJ5KCJmYWN0b2V4dHJhIikKbGlicmFyeSgiYmVlc3dhcm0iKQpsaWJyYXJ5KCJzY2FsZXMiKQpsaWJyYXJ5KCJSQ29sb3JCcmV3ZXIiKQpsaWJyYXJ5KCJSQU5OIikKbGlicmFyeSgidG0iKQpsaWJyYXJ5KCJ0b3BpY21vZGVscyIpCmxpYnJhcnkoInN0cmluZ3IiKQpsaWJyYXJ5KCJnZ3Bsb3QyIikKI2xpYnJhcnkoImdncmlkZ2VzIikKI2xpYnJhcnkoInZpcmlkaXMiKQpsaWJyYXJ5KCJ3b3JkY2xvdWQiKQpsaWJyYXJ5KCJ3b3JkY2xvdWQyIikKbGlicmFyeSgidGlkeXRleHQiKQpsaWJyYXJ5KCJrbml0ciIpCmxpYnJhcnkoInRpZHl2ZXJzZSIpCgojc291cmNlKCIuLi9saWIvcGxvdHN0YWNrZWQuUiIpCnNvdXJjZSgiLi4vbGliL3NwZWVjaEZ1bmNzLlIiKQpzb3VyY2UoIi4uL2xpYi93b3JkY2xvdWRGdW5jcy5SIikKCmBgYAoKIyMgTG9hZCB0aGUgZGF0YXNldApUaGUgZGF0YSBzZXQgKi4uL2RhdGEvcGhpbG9zb3BoeV9kYXRhLmNzdiogY29udGFpbnMgMzYwODA4IHNlbnRlbmNlcyB0YWtlbiBmcm9tIDUxIHRleHRzIHNwYW5uaW5nIHRoZSBoaXN0b3J5IG9mIHBoaWxvc29waHkuIFlvdSBjYW4gZmluZCBtb3JlIGRldGFpbHMgYWJvdXQgaXQgaW4gW2h0dHBzOi8vd3d3LmthZ2dsZS5jb20va291cm9zaGFsaXphZGVoL2hpc3Rvcnktb2YtcGhpbG9zb3BoeV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9rb3Vyb3NoYWxpemFkZWgvaGlzdG9yeS1vZi1waGlsb3NvcGh5KS4gCgpgYGB7ciByZWFkIGRhdGEsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmZpbGU8LScuLi9kYXRhL3BoaWxvc29waHlfZGF0YS5jc3YnCmZ1bGxfZGF0YSA8LSByZWFkLmNzdihmaWxlKQpmdWxsX2RhdGEgPC0gZnVsbF9kYXRhICU+JSAKICBtdXRhdGUod29yZC5jb3VudCA9IGYud29yZF9jb3VudChzZW50ZW5jZV9zcGFjeSkpCiMgc2VudGVuY2UubGlzdCBpcyBnZW5lcmF0ZWQgZnJvbSB0aGUgY2h1bmsge3IgZ2VuZXJhdGUgc2VudGVuY2UubGlzdH0uIFRoaXMgd2lsbCAKIyBjb3N0IDI1LTMwIG1pbnV0ZXMuIFRvIHNhdmUgeW91ciB0aW1lLCB5b3UgY2FuIHNpbXBseSB1c2UgaXQuCiMgRmVlbCBmcmVlIGlmIHlvdSBkb24ndCB3YW50IHRvIHJ1biB7ciBnZW5lcmF0ZSBzZW50ZW5jZS5saXN0fQpzdWJmaWxlIDwtICcuLi9vdXRwdXQvc2VudGVuY2UubGlzdC5jc3YnCnNlbnRlbmNlLmxpc3QgPC0gcmVhZC5jc3Yoc3ViZmlsZSkKYGBgCgoKYGBge3IgLHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CgpyZWR1Y2VkX2RhdGEgPSBmdWxsX2RhdGEgJT4lIHNlbGVjdCh0aXRsZSwgYXV0aG9yLCBzY2hvb2wsIHNlbnRlbmNlX3NwYWN5LCBvcmlnaW5hbF9wdWJsaWNhdGlvbl9kYXRlLCBzZW50ZW5jZV9sZW5ndGgsIHdvcmQuY291bnQpCgojdHJpYWxfZGF0YSA8LSByZWR1Y2VkX2RhdGFbMToxMDAwLF0KZGF0YSA8LSByZWR1Y2VkX2RhdGEgJT4lIGZpbHRlcihzY2hvb2wgPT0gImNhcGl0YWxpc20iIHwgc2Nob29sID09ICJjb21tdW5pc20iKQpgYGAKCgojIFN0ZXAgOiBMZW5ndGggb2Ygc2VudGVuY2VzIG9mIGRpZmZlcmVudCBzY2hvb2xzPwoKYGBge3IgLHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmRhdGEuYnlzY2hvb2wgPC0gcmVkdWNlZF9kYXRhICU+JSBncm91cF9ieShzY2hvb2wpICU+JQogIHN1bW1hcmlzZShtZWFubGVuZ3RoID0gbWVhbih3b3JkLmNvdW50KSkgJT4lCiAgYXJyYW5nZShtZWFubGVuZ3RoKQogIApnMSA8LSBkYXRhLmJ5c2Nob29sICU+JSBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKHNjaG9vbCwgbWVhbmxlbmd0aCksIHkgPSBtZWFubGVuZ3RoLCBmaWxsID0gc2Nob29sKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJCYXIgcGxvdDogbWVhbiBsZW5ndGggb2Ygc2VudGVuY2VzKHdvcmQgY291bnQpIG9mIGRpZmZlcmVudCBzY2hvb2xzIiwKICAgIHggPSAiU2Nob29scyIsCiAgICB5ID0gIk1lYW4gTGVuZ3RoIG9mIFNlbnRlbmNlcyIKICApICsKICBjb29yZF9mbGlwKCkKCmcxCmBgYAoKSW4gYWRkaXRpb24gdG8gdGhlIG1lYW4gbGVuZ3RoIG9mIHNlbnRlbmNlcywgdGhpcyBwbG90IHdpbGwgc2hvdyBtb3JlIGRldGFpbHMgb2YgYWN0dWFsIGRpc3RyaWJ1dG9uIG9mIHNlbnRlbmNlIGxlbmd0aC4KCmBgYHtyLCBmaWcud2lkdGggPSAzLCBmaWcuaGVpZ2h0ID0gM30KZGF0YS5ieXNjaG9vbCA8LSByZWR1Y2VkX2RhdGEgJT4lIGdyb3VwX2J5KHNjaG9vbCkgCmcyIDwtIGRhdGEuYnlzY2hvb2wgJT4lIGdncGxvdChhZXMoeCA9IHNjaG9vbCwgeSA9IHdvcmQuY291bnQsIGZpbGwgPSBzY2hvb2wpKSArCiAgZ2VvbV92aW9saW4oYWxwaGEgPSAwLjUpICsKICAjZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcihzZWVkID0gMSwgd2lkdGggPSAwLjIpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2VvbV9ib3hwbG90KHdpZHRoPS4xKSArCiAgbGFicygKICAgIHRpdGxlID0gInZpb2xpbiBwbG90ICsgYm94IHBsb3Q6IHNwcmVhZCBvZiBzZW50ZW5jZXMnIGxlbmd0aCBcbiBvZiBkaWZmZXJlbnQgc2Nob29scyIsCiAgICB4ID0gIlNjaG9vbHMiLAogICAgeSA9ICJMZW5ndGggb2YgU2VudGVuY2VzIgogICkgKwogIGNvb3JkX2ZsaXAoKQoKZzIKYGBgCgoKCgojIFN0ZXAgMTogV2hhdCBhcmUgdGhlIGZyZXF1ZW50bHkgbWVudGlvbmVkIHdvcmRzPwpMZXQncyBoYXZlIGFuIG92ZXJ2aWV3IG9mIGZyZXF1ZW5jeSBvZiB3b3JkcyBpbiB0aGUgd2hvbGUgY29ycHVzLgoKCgpgYGB7ciBwcmVwYXJlIGNvcnB1cywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp0ZXh0IDwtIGZ1bGxfZGF0YSRzZW50ZW5jZV9sb3dlcmVkCmRvY3MgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0ZXh0KSkKYGBgCgpgYGB7ciBjbGVhbiBjb3JwdXMgYW5kIG1ha2UgZHRtLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CnJtX3dvcmRzID0gYygnYWxzbycsICdhcmVhcycsICdjYW4nLCAnZXRjJywgJ2dldCcsICdqdXN0JywgJ2xpa2UnLAonbG90JywgJ21hbnknLCAnbWF5JywgJ25lZWQnLCAnb25lJywgJ3MnLCAnc2V0JywgJ3QnLAondGltZScsICd1cycsICd1c2UnLCAnd2F5JywgJ3dlbGwnLCAnd2lsbCcsICdiJywgJ2UnLAonZycsICdsZXNzJywgJ2dpdmUnLCAndGVsbCcsICdpbScsICd0YWtlJywgJ2NvbWluZycsCidzYXknLCAncmVhbGx5JywgJ211c3QnKQoKZG9jcyA8LSBmLmNsZWFuLmNvcnB1cyhkb2NzKQp0ZG0ub3ZlcmFsbCA8LSBmLm1ha2UudGRtKGRvY3MpCmBgYAoKCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9Niwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp3b3JkY2xvdWQodGRtLm92ZXJhbGwkdGVybSwgdGRtLm92ZXJhbGwkYHN1bShjb3VudClgLAogICAgICAgICAgc2NhbGU9Yyg1LDAuOCksCiAgICAgICAgICBtYXgud29yZHM9MjAwLAogICAgICAgICAgbWluLmZyZXE9MSwKICAgICAgICAgIHJhbmRvbS5vcmRlcj1GQUxTRSwKICAgICAgICAgIHJvdC5wZXI9MC4zLAogICAgICAgICAgcmFuZG9tLmNvbG9yPUZBTFNFLAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwiRGFyazIiKSkKYGBgCgojIyMgTm93IGxldCdzIHNlZSB0aGUgd29yZCBjbG91ZHMgb2YgZGlmZmVyZW50IHNjaG9vbHMuCkNhcGl0YWxpc206CgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp0ZXh0LmNhcGl0YWxpc20gPC0gZnVsbF9kYXRhICU+JSBmaWx0ZXIoc2Nob29sID09ICJjYXBpdGFsaXNtIikKdGV4dC5jYXBpdGFsaXNtIDwtIHRleHQuY2FwaXRhbGlzbSRzZW50ZW5jZV9sb3dlcmVkCmRvY3MgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0ZXh0LmNhcGl0YWxpc20pKQpkb2NzIDwtIGYuY2xlYW4uY29ycHVzKGRvY3MpCnRkbS5vdmVyYWxsIDwtIGYubWFrZS50ZG0oZG9jcykKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTYsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0Kd29yZGNsb3VkKHRkbS5vdmVyYWxsJHRlcm0sIHRkbS5vdmVyYWxsJGBzdW0oY291bnQpYCwKICAgICAgICAgIHNjYWxlPWMoNSwxLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwKICAgICAgICAgIG1pbi5mcmVxPTEsCiAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICByb3QucGVyPTAuMywKICAgICAgICAgIHJhbmRvbS5jb2xvcj1GQUxTRSwKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDksIkJsdWVzIikpCmBgYApFbXBpcmljaXNtOgoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0KdGV4dC5lbXBpcmljaXNtIDwtIGZ1bGxfZGF0YSAlPiUgZmlsdGVyKHNjaG9vbCA9PSAiZW1waXJpY2lzbSIpCnRleHQuZW1waXJpY2lzbSA8LSB0ZXh0LmVtcGlyaWNpc20kc2VudGVuY2VfbG93ZXJlZApkb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dC5lbXBpcmljaXNtKSkKZG9jcyA8LSBmLmNsZWFuLmNvcnB1cyhkb2NzKQp0ZG0ub3ZlcmFsbCA8LSBmLm1ha2UudGRtKGRvY3MpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CndvcmRjbG91ZCh0ZG0ub3ZlcmFsbCR0ZXJtLCB0ZG0ub3ZlcmFsbCRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMS41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICByYW5kb20uY29sb3I9RkFMU0UsCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg5LCJCbHVlcyIpKQpgYGAKCkdlcm1hbl9pZGVhbGlzbToKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CnRleHQuZ2VybWFuX2lkZWFsaXNtIDwtIGZ1bGxfZGF0YSAlPiUgZmlsdGVyKHNjaG9vbCA9PSAiZ2VybWFuX2lkZWFsaXNtIikKdGV4dC5nZXJtYW5faWRlYWxpc20gPC0gdGV4dC5nZXJtYW5faWRlYWxpc20kc2VudGVuY2VfbG93ZXJlZApkb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dC5nZXJtYW5faWRlYWxpc20pKQpkb2NzIDwtIGYuY2xlYW4uY29ycHVzKGRvY3MpCnRkbS5vdmVyYWxsIDwtIGYubWFrZS50ZG0oZG9jcykKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTYsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0Kd29yZGNsb3VkKHRkbS5vdmVyYWxsJHRlcm0sIHRkbS5vdmVyYWxsJGBzdW0oY291bnQpYCwKICAgICAgICAgIHNjYWxlPWMoNSwxLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwKICAgICAgICAgIG1pbi5mcmVxPTEsCiAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICByb3QucGVyPTAuMywKICAgICAgICAgIHJhbmRvbS5jb2xvcj1GQUxTRSwKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDksIkJsdWVzIikpCmBgYApDb250aW5lbnRhbDoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CnRleHQuY29udGluZW50YWwgPC0gZnVsbF9kYXRhICU+JSBmaWx0ZXIoc2Nob29sID09ICJjb250aW5lbnRhbCIpCnRleHQuY29udGluZW50YWwgPC0gdGV4dC5jb250aW5lbnRhbCRzZW50ZW5jZV9sb3dlcmVkCmRvY3MgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0ZXh0LmNvbnRpbmVudGFsKSkKZG9jcyA8LSBmLmNsZWFuLmNvcnB1cyhkb2NzKQp0ZG0ub3ZlcmFsbCA8LSBmLm1ha2UudGRtKGRvY3MpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CndvcmRjbG91ZCh0ZG0ub3ZlcmFsbCR0ZXJtLCB0ZG0ub3ZlcmFsbCRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMS41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICByYW5kb20uY29sb3I9RkFMU0UsCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg5LCJCbHVlcyIpKQpgYGAKCgpSYXRpb25hbGlzbToKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CnRleHQucmF0aW9uYWxpc20gPC0gZnVsbF9kYXRhICU+JSBmaWx0ZXIoc2Nob29sID09ICJyYXRpb25hbGlzbSIpCnRleHQucmF0aW9uYWxpc20gPC0gdGV4dC5yYXRpb25hbGlzbSRzZW50ZW5jZV9sb3dlcmVkCmRvY3MgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0ZXh0LnJhdGlvbmFsaXNtKSkKZG9jcyA8LSBmLmNsZWFuLmNvcnB1cyhkb2NzKQp0ZG0ub3ZlcmFsbCA8LSBmLm1ha2UudGRtKGRvY3MpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CndvcmRjbG91ZCh0ZG0ub3ZlcmFsbCR0ZXJtLCB0ZG0ub3ZlcmFsbCRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMS41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICByYW5kb20uY29sb3I9RkFMU0UsCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg5LCJCbHVlcyIpKQpgYGAKCkFyaXN0b3RsZToKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CnRleHQuYXJpc3RvdGxlIDwtIGZ1bGxfZGF0YSAlPiUgZmlsdGVyKHNjaG9vbCA9PSAiYXJpc3RvdGxlIikKdGV4dC5hcmlzdG90bGUgPC0gdGV4dC5hcmlzdG90bGUkc2VudGVuY2VfbG93ZXJlZApkb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dC5hcmlzdG90bGUpKQpkb2NzIDwtIGYuY2xlYW4uY29ycHVzKGRvY3MpCnRkbS5vdmVyYWxsIDwtIGYubWFrZS50ZG0oZG9jcykKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTYsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0Kd29yZGNsb3VkKHRkbS5vdmVyYWxsJHRlcm0sIHRkbS5vdmVyYWxsJGBzdW0oY291bnQpYCwKICAgICAgICAgIHNjYWxlPWMoNSwxLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwKICAgICAgICAgIG1pbi5mcmVxPTEsCiAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICByb3QucGVyPTAuMywKICAgICAgICAgIHJhbmRvbS5jb2xvcj1GQUxTRSwKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDksIkJsdWVzIikpCmBgYAoKRmVtaW5pc206CgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp0ZXh0LmZlbWluaXNtIDwtIGZ1bGxfZGF0YSAlPiUgZmlsdGVyKHNjaG9vbCA9PSAiZmVtaW5pc20iKQp0ZXh0LmZlbWluaXNtIDwtIHRleHQuZmVtaW5pc20kc2VudGVuY2VfbG93ZXJlZApkb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dC5mZW1pbmlzbSkpCmRvY3MgPC0gZi5jbGVhbi5jb3JwdXMoZG9jcykKdGRtLm92ZXJhbGwgPC0gZi5tYWtlLnRkbShkb2NzKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9Niwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp3b3JkY2xvdWQodGRtLm92ZXJhbGwkdGVybSwgdGRtLm92ZXJhbGwkYHN1bShjb3VudClgLAogICAgICAgICAgc2NhbGU9Yyg1LDEuNSksCiAgICAgICAgICBtYXgud29yZHM9MTAwLAogICAgICAgICAgbWluLmZyZXE9MSwKICAgICAgICAgIHJhbmRvbS5vcmRlcj1GQUxTRSwKICAgICAgICAgIHJvdC5wZXI9MC4zLAogICAgICAgICAgcmFuZG9tLmNvbG9yPUZBTFNFLAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOSwiQmx1ZXMiKSkKYGBgCgpDb21tdW5pc206CgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp0ZXh0LmNvbW11bmlzbSA8LSBmdWxsX2RhdGEgJT4lIGZpbHRlcihzY2hvb2wgPT0gImNvbW11bmlzbSIpCnRleHQuY29tbXVuaXNtIDwtIHRleHQuY29tbXVuaXNtJHNlbnRlbmNlX2xvd2VyZWQKZG9jcyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHQuY29tbXVuaXNtKSkKZG9jcyA8LSBmLmNsZWFuLmNvcnB1cyhkb2NzKQp0ZG0ub3ZlcmFsbCA8LSBmLm1ha2UudGRtKGRvY3MpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CndvcmRjbG91ZCh0ZG0ub3ZlcmFsbCR0ZXJtLCB0ZG0ub3ZlcmFsbCRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMS41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICByYW5kb20uY29sb3I9RkFMU0UsCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg5LCJCbHVlcyIpKQpgYGAKClBoZW5vbWVub2xvZ3k6IAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0KdGV4dC5waGVub21lbm9sb2d5IDwtIGZ1bGxfZGF0YSAlPiUgZmlsdGVyKHNjaG9vbCA9PSAicGhlbm9tZW5vbG9neSIpCnRleHQucGhlbm9tZW5vbG9neSA8LSB0ZXh0LnBoZW5vbWVub2xvZ3kkc2VudGVuY2VfbG93ZXJlZApkb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dC5waGVub21lbm9sb2d5KSkKZG9jcyA8LSBmLmNsZWFuLmNvcnB1cyhkb2NzKQp0ZG0ub3ZlcmFsbCA8LSBmLm1ha2UudGRtKGRvY3MpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CndvcmRjbG91ZCh0ZG0ub3ZlcmFsbCR0ZXJtLCB0ZG0ub3ZlcmFsbCRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMS41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICByYW5kb20uY29sb3I9RkFMU0UsCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg5LCJCbHVlcyIpKQpgYGAKCnN0b2ljaXNtOgoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0KdGV4dC5zdG9pY2lzbSA8LSBmdWxsX2RhdGEgJT4lIGZpbHRlcihzY2hvb2wgPT0gInN0b2ljaXNtIikKdGV4dC5zdG9pY2lzbSA8LSB0ZXh0LnN0b2ljaXNtJHNlbnRlbmNlX2xvd2VyZWQKZG9jcyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHQuc3RvaWNpc20pKQpkb2NzIDwtIGYuY2xlYW4uY29ycHVzKGRvY3MpCnRkbS5vdmVyYWxsIDwtIGYubWFrZS50ZG0oZG9jcykKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTYsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0Kd29yZGNsb3VkKHRkbS5vdmVyYWxsJHRlcm0sIHRkbS5vdmVyYWxsJGBzdW0oY291bnQpYCwKICAgICAgICAgIHNjYWxlPWMoNSwxLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwKICAgICAgICAgIG1pbi5mcmVxPTEsCiAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICByb3QucGVyPTAuMywKICAgICAgICAgIHJhbmRvbS5jb2xvcj1GQUxTRSwKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDksIkJsdWVzIikpCmBgYAoKQW5hbHl0aWM6CgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp0ZXh0LmFuYWx5dGljIDwtIGZ1bGxfZGF0YSAlPiUgZmlsdGVyKHNjaG9vbCA9PSAiYW5hbHl0aWMiKQp0ZXh0LmFuYWx5dGljIDwtIHRleHQuYW5hbHl0aWMkc2VudGVuY2VfbG93ZXJlZApkb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dC5hbmFseXRpYykpCmRvY3MgPC0gZi5jbGVhbi5jb3JwdXMoZG9jcykKdGRtLm92ZXJhbGwgPC0gZi5tYWtlLnRkbShkb2NzKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9Niwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp3b3JkY2xvdWQodGRtLm92ZXJhbGwkdGVybSwgdGRtLm92ZXJhbGwkYHN1bShjb3VudClgLAogICAgICAgICAgc2NhbGU9Yyg1LDEuNSksCiAgICAgICAgICBtYXgud29yZHM9MTAwLAogICAgICAgICAgbWluLmZyZXE9MSwKICAgICAgICAgIHJhbmRvbS5vcmRlcj1GQUxTRSwKICAgICAgICAgIHJvdC5wZXI9MC4zLAogICAgICAgICAgcmFuZG9tLmNvbG9yPUZBTFNFLAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOSwiQmx1ZXMiKSkKYGBgCgpOaWV0enNjaGU6CgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQp0ZXh0Lm5pZXR6c2NoZSA8LSBmdWxsX2RhdGEgJT4lIGZpbHRlcihzY2hvb2wgPT0gIm5pZXR6c2NoZSIpCnRleHQubmlldHpzY2hlIDwtIHRleHQubmlldHpzY2hlJHNlbnRlbmNlX2xvd2VyZWQKZG9jcyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHQubmlldHpzY2hlKSkKZG9jcyA8LSBmLmNsZWFuLmNvcnB1cyhkb2NzKQp0ZG0ub3ZlcmFsbCA8LSBmLm1ha2UudGRtKGRvY3MpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD02LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGVjaG89RkFMU0V9CndvcmRjbG91ZCh0ZG0ub3ZlcmFsbCR0ZXJtLCB0ZG0ub3ZlcmFsbCRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMS41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICByYW5kb20uY29sb3I9RkFMU0UsCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg5LCJCbHVlcyIpKQpgYGAKClBsYXRvOgoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0KdGV4dC5wbGF0byA8LSBmdWxsX2RhdGEgJT4lIGZpbHRlcihzY2hvb2wgPT0gInBsYXRvIikKdGV4dC5wbGF0byA8LSB0ZXh0LnBsYXRvJHNlbnRlbmNlX2xvd2VyZWQKZG9jcyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHQucGxhdG8pKQpkb2NzIDwtIGYuY2xlYW4uY29ycHVzKGRvY3MpCnRkbS5vdmVyYWxsIDwtIGYubWFrZS50ZG0oZG9jcykKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTYsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0Kd29yZGNsb3VkKHRkbS5vdmVyYWxsJHRlcm0sIHRkbS5vdmVyYWxsJGBzdW0oY291bnQpYCwKICAgICAgICAgIHNjYWxlPWMoNSwxLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwKICAgICAgICAgIG1pbi5mcmVxPTEsCiAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICByb3QucGVyPTAuMywKICAgICAgICAgIHJhbmRvbS5jb2xvcj1GQUxTRSwKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDksIkJsdWVzIikpCmBgYAoKCgoKCiMgU3RlcCA6IHNlbnRpbWVudCBhbmFseXNpcyBvbiBDYXBpdGFsaXNtIGFuZCBDb21tdW5pc20KCmBgYHtyIGdlbmVyYXRlIHNlbnRlbmNlLmxpc3QsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsZWNobz1GQUxTRX0KIyBzZW50ZW5jZS5saXN0PU5VTEwKIyAKIyBmb3IoaSBpbiAxOm5yb3coZGF0YSkpewojICAgc2VudGVuY2VzIDwtIGRhdGEkc2VudGVuY2Vfc3BhY3lbaV0KIyAgIGlmKGxlbmd0aChzZW50ZW5jZXMpPjApewojICAgICBlbW90aW9ucz1nZXRfbnJjX3NlbnRpbWVudChzZW50ZW5jZXMpCiMgICAgICN3b3JkLmNvdW50PXdvcmRfY291bnQoc2VudGVuY2VzKQojICAgICAjIGNvbG5hbWVzKGVtb3Rpb25zKT1wYXN0ZTAoImVtby4iLCBjb2xuYW1lcyhlbW90aW9ucykpCiMgICAgICMgaW4gY2FzZSB0aGUgd29yZCBjb3VudHMgYXJlIHplcm9zPwojICAgICAjZW1vdGlvbnM9ZGlhZygxLyh0cmlhbF9kYXRhJHNlbnRlbmNlX2xlbmd0aFsxXSswLjAxKSklKiVhcy5tYXRyaXgoZW1vdGlvbnMpCiMgICAgIGVtb3Rpb25zID0gYXMubWF0cml4KGVtb3Rpb25zKQojICAgICBzZW50ZW5jZS5saXN0PXJiaW5kKHNlbnRlbmNlLmxpc3QsCiMgICAgICAgICAgICAgICAgICAgICAgICAgY2JpbmQoZGF0YVtpLF0sCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VudGVuY2VzPWFzLmNoYXJhY3RlcihzZW50ZW5jZXMpLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICN3b3JkLmNvdW50LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVtb3Rpb25zLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnQuaWQ9aQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgKQojICAgfQojIH0KIwojIHNlbnRlbmNlLmxpc3QgPC0gc2VudGVuY2UubGlzdCAlPiUgbGVmdF9qb2luKGRhdGEpICNqb2luIHRoZSB3b3JkLmNvdW50IGludG8gc2VudGVuY2UubGlzdAojd3JpdGUuY3N2KHNlbnRlbmNlLmxpc3QsIi9Vc2Vycy9qaXVydXdhbmcvRG9jdW1lbnRzL0dpdEh1Yi9zcHJpbmctMjAyMi1wcmoxLWpyd2FuZzA4MTAvb3V0cHV0L3NlbnRlbmNlLmxpc3QuY3N2IikKYGBgCgoKCgoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9Cm5hbWVzKHNlbnRlbmNlLmxpc3QpCmBgYAoKIyMgRW1vdGlvbmFsbHkgY2hhcmdlZCBzZW50ZW5jZXMKCkNhcGl0YWxpc206CmBgYHtyfQplbW90aW9ucy50eXBlcz1jKCJhbnRpY2lwYXRpb24iLCAiam95IiwgInN1cnByaXNlIiwgInRydXN0IiwKICAgICAgICAgICAgICAgICAiYW5nZXIiLCAiZGlzZ3VzdCIsICJmZWFyIiwgInNhZG5lc3MiLCAibmVnYXRpdmUiLCAicG9zaXRpdmUiKQoKc3BlZWNoLmRmPXRibF9kZihzZW50ZW5jZS5saXN0KSAlPiUKICBmaWx0ZXIoc2Nob29sID09ICJjYXBpdGFsaXNtIiwgd29yZC5jb3VudCA8IDIwKSAlPiUKICBzZWxlY3Qoc2VudGVuY2VzLCBhbmdlcjpwb3NpdGl2ZSkKc3BlZWNoLmRmPWFzLmRhdGEuZnJhbWUoc3BlZWNoLmRmKQphcy5jaGFyYWN0ZXIoc3BlZWNoLmRmJHNlbnRlbmNlc1thcHBseShzcGVlY2guZGZbLC0xXSwgMiwgd2hpY2gubWF4KV0pCmBgYAoKQ29tbXVuaXNtOgpgYGB7cn0KCnNwZWVjaC5kZj10YmxfZGYoc2VudGVuY2UubGlzdCkgJT4lCiAgZmlsdGVyKHNjaG9vbCA9PSAiY29tbXVuaXNtIiwgd29yZC5jb3VudCA8IDIwKSAlPiUKICBzZWxlY3Qoc2VudGVuY2VzLCBhbmdlcjpwb3NpdGl2ZSkKc3BlZWNoLmRmPWFzLmRhdGEuZnJhbWUoc3BlZWNoLmRmKQphcy5jaGFyYWN0ZXIoc3BlZWNoLmRmJHNlbnRlbmNlc1thcHBseShzcGVlY2guZGZbLC0xXSwgMiwgd2hpY2gubWF4KV0pCmBgYAoKIyMgQ2x1c3RlcmluZyBvZiBlbW90aW9ucwoKQ2FwaXRhbGlzbToKYGBge3J9CmhlYXRtYXAuMihjb3Ioc2VudGVuY2UubGlzdCU+JWZpbHRlcihzY2hvb2w9PSJjYXBpdGFsaXNtIiklPiVzZWxlY3QoYW5nZXI6cG9zaXRpdmUpKSwgCiAgICAgICAgICBzY2FsZSA9ICJub25lIiwgCiAgICAgICAgICBjb2wgPSBibHVlcmVkKDEwMCksICwgbWFyZ2luPWMoNiwgNiksIGtleT1GLAogICAgICAgICAgdHJhY2UgPSAibm9uZSIsIGRlbnNpdHkuaW5mbyA9ICJub25lIikKcGFyKG1hcj1jKDQsIDYsIDIsIDEpKQpgYGAKCkNvbW11bmlzbToKYGBge3J9CmhlYXRtYXAuMihjb3Ioc2VudGVuY2UubGlzdCU+JWZpbHRlcihzY2hvb2w9PSJjb21tdW5pc20iKSU+JXNlbGVjdChhbmdlcjpwb3NpdGl2ZSkpLCAKICAgICAgICAgIHNjYWxlID0gIm5vbmUiLCAKICAgICAgICAgIGNvbCA9IGJsdWVyZWQoMTAwKSwgLCBtYXJnaW49Yyg2LCA2KSwga2V5PUYsCiAgICAgICAgICB0cmFjZSA9ICJub25lIiwgZGVuc2l0eS5pbmZvID0gIm5vbmUiKQpwYXIobWFyPWMoNCwgNiwgMiwgMSkpCmBgYAoKCgpgYGB7cn0Kc2VudGVuY2UubGlzdC5jYXBpdGFsaXNtIDwtIHNlbnRlbmNlLmxpc3QgJT4lIGZpbHRlcihzY2hvb2w9PSJjYXBpdGFsaXNtIikKZW1vLm1lYW5zMT1jb2xNZWFucyhzZWxlY3Qoc2VudGVuY2UubGlzdC5jYXBpdGFsaXNtLCBhbmdlcjpwb3NpdGl2ZSk+MC4wMSkKY29sLnVzZTE9YygicmVkMiIsICJkYXJrZ29sZGVucm9kMSIsICJjaGFydHJldXNlMyIsImJsdWV2aW9sZXQiLCAiZGFya2dvbGRlbnJvZDEiLCAiZG9kZ2VyYmx1ZTMiLCAiZGFya2dvbGRlbnJvZDEiLCAiZGFya2dvbGRlbnJvZDEiLCAiYmxhY2siLCAiZGFya2dvbGRlbnJvZDEiKQpiYXJwbG90KGVtby5tZWFuczFbb3JkZXIoZW1vLm1lYW5zMSldLCBsYXM9MiwgY29sPWNvbC51c2UxW29yZGVyKGVtby5tZWFuczEpXSwgaG9yaXo9VCwKICAgICAgICBjZXgubmFtZXM9MC43LCBtYWluPSJDYXBpdGFsaXNtIikKYGBgCgpgYGB7cn0Kc2VudGltZW50LmRmMSA8LSBkYXRhLmZyYW1lKAogIGdyb3VwPWMoImFuZ2VyIiwgImFudGljaXBhdGlvbiIsICJkaXNndXN0IiwiZmVhciIsICJqb3kiLCAic2FkbmVzcyIsICJzdXJwcmlzZSIsICJ0cnVzdCIsICJuZWdhdGl2ZSIsICJwb3NpdGl2ZSIpLAogIHZhbHVlPWVtby5tZWFuczEKKQoKc2VudGltZW50LmRmMSA8LSBzZW50aW1lbnQuZGYxICU+JSAKICBtdXRhdGUocGVyYyA9IHZhbHVlIC8gc3VtKHZhbHVlKSkgJT4lIAogIGFycmFuZ2UocGVyYykgJT4lCiAgbXV0YXRlKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudChwZXJjKSkKCgpnZ3Bsb3Qoc2VudGltZW50LmRmMSwgYWVzKHg9IiIsIHk9cGVyYywgZmlsbD1ncm91cCkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTEsIGNvbG9yPSJ3aGl0ZSIpICsKICBjb29yZF9wb2xhcigieSIsIHN0YXJ0PTApICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbGFiZWxzKSwgCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLAogICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIHNpemU9MykgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IlNwZWN0cmFsIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQZXJjZW50YWdlIG9mIHRoZSBzZW50aW1lbnQgaW4gQ2FwaXRhbGlzbSIsCiAgICB4ID0gIiIsCiAgICB5ID0gIiIsCiAgKQpgYGAKCgoKCgpgYGB7cn0Kc2VudGVuY2UubGlzdC5jb21tdW5pc20gPC0gc2VudGVuY2UubGlzdCAlPiUgZmlsdGVyKHNjaG9vbD09ImNvbW11bmlzbSIpCmVtby5tZWFuczI9Y29sTWVhbnMoc2VsZWN0KHNlbnRlbmNlLmxpc3QuY29tbXVuaXNtLCBhbmdlcjpwb3NpdGl2ZSk+MC4wMSkKY29sLnVzZTI9YygicmVkMiIsICJkYXJrZ29sZGVucm9kMSIsICJjaGFydHJldXNlMyIsImJsdWV2aW9sZXQiLCAiZGFya2dvbGRlbnJvZDEiLCAiZG9kZ2VyYmx1ZTMiLCAiZGFya2dvbGRlbnJvZDEiLCAiZGFya2dvbGRlbnJvZDEiLCAiYmxhY2siLCAiZGFya2dvbGRlbnJvZDEiKQpiYXJwbG90KGVtby5tZWFuczJbb3JkZXIoZW1vLm1lYW5zMildLCBsYXM9MiwgY29sPWNvbC51c2UyW29yZGVyKGVtby5tZWFuczIpXSwgaG9yaXo9VCwKICAgICAgICBjZXgubmFtZXM9MC43LCBtYWluPSJDb21tdW5pc20iKQpgYGAKCgpgYGB7cn0Kc2VudGltZW50LmRmMiA8LSBkYXRhLmZyYW1lKAogIGdyb3VwPWMoImFuZ2VyIiwgImFudGljaXBhdGlvbiIsICJkaXNndXN0IiwiZmVhciIsICJqb3kiLCAic2FkbmVzcyIsICJzdXJwcmlzZSIsICJ0cnVzdCIsICJuZWdhdGl2ZSIsICJwb3NpdGl2ZSIpLAogIHZhbHVlPWVtby5tZWFuczIKKQoKc2VudGltZW50LmRmMiA8LSBzZW50aW1lbnQuZGYyICU+JSAKICBtdXRhdGUocGVyYyA9IHZhbHVlIC8gc3VtKHZhbHVlKSkgJT4lIAogIGFycmFuZ2UocGVyYykgJT4lCiAgbXV0YXRlKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudChwZXJjKSkKCgpnZ3Bsb3Qoc2VudGltZW50LmRmMiwgYWVzKHg9IiIsIHk9cGVyYywgZmlsbD1ncm91cCkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTEsIGNvbG9yPSJ3aGl0ZSIpICsKICBjb29yZF9wb2xhcigieSIsIHN0YXJ0PTApICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbGFiZWxzKSwgCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLAogICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsIHNpemU9MykgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IlNwZWN0cmFsIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQZXJjZW50YWdlIG9mIHRoZSBzZW50aW1lbnQgaW4gQ29tbXVuaXNtIiwKICAgIHggPSAiIiwKICAgIHkgPSAiIiwKICApCmBgYAoKCgoKYGBge3J9CnNlbnRpbWVudC5kZi5hbGwgPC0gZGF0YS5mcmFtZSgKICBncm91cD1jKCJhbmdlciIsICJhbnRpY2lwYXRpb24iLCAiZGlzZ3VzdCIsImZlYXIiLCAiam95IiwgInNhZG5lc3MiLCAic3VycHJpc2UiLCAidHJ1c3QiLCAibmVnYXRpdmUiLCAicG9zaXRpdmUiKSwKICBjYXBpdGFsaXNtPWVtby5tZWFuczEsCiAgY29tbXVuaXNtPWVtby5tZWFuczIKKQoKc2VudGltZW50LmRmLmFsbC5sb25nIDwtIHNlbnRpbWVudC5kZi5hbGwgJT4lIHBpdm90X2xvbmdlcihjKCJjYXBpdGFsaXNtIiwgImNvbW11bmlzbSIpKQoKZzMgPC0gc2VudGltZW50LmRmLmFsbC5sb25nICU+JSBnZ3Bsb3QoYWVzKHggPSBncm91cCwgeSA9IHZhbHVlLCBmaWxsID0gbmFtZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBsYWJzKAogICAgeCA9ICIiLAogICAgeSA9ICJtZWFuIHNjb3JlIG9mIHNlbnRpbWVudCIsCiAgICB0aXRsZSA9ICJTZW50aW1lbnQgY29tcGFyaXNvbjogQ2FwaXRhbGlzbSB2cy4gQ29tbXVuaXNtIgogICkKCmczCmBgYAoKCgpgYGB7cn0Kc2VudGVuY2UubGlzdC5NYXJ4IDwtIHNlbnRlbmNlLmxpc3QgJT4lIGZpbHRlcihhdXRob3I9PSJNYXJ4IikKZW1vLm1lYW5zLk1hcng9Y29sTWVhbnMoc2VsZWN0KHNlbnRlbmNlLmxpc3QuTWFyeCwgYW5nZXI6cG9zaXRpdmUpPjAuMDEpCgpzZW50ZW5jZS5saXN0LkxlbmluIDwtIHNlbnRlbmNlLmxpc3QgJT4lIGZpbHRlcihhdXRob3I9PSJMZW5pbiIpCmVtby5tZWFucy5MZW5pbj1jb2xNZWFucyhzZWxlY3Qoc2VudGVuY2UubGlzdC5MZW5pbiwgYW5nZXI6cG9zaXRpdmUpPjAuMDEpCgpzZW50ZW5jZS5saXN0LlNtaXRoIDwtIHNlbnRlbmNlLmxpc3QgJT4lIGZpbHRlcihhdXRob3I9PSJTbWl0aCIpCmVtby5tZWFucy5TbWl0aD1jb2xNZWFucyhzZWxlY3Qoc2VudGVuY2UubGlzdC5TbWl0aCwgYW5nZXI6cG9zaXRpdmUpPjAuMDEpCgpzZW50ZW5jZS5saXN0LlJpY2FyZG8gPC0gc2VudGVuY2UubGlzdCAlPiUgZmlsdGVyKGF1dGhvcj09IlJpY2FyZG8iKQplbW8ubWVhbnMuUmljYXJkbz1jb2xNZWFucyhzZWxlY3Qoc2VudGVuY2UubGlzdC5SaWNhcmRvLCBhbmdlcjpwb3NpdGl2ZSk+MC4wMSkKCnNlbnRlbmNlLmxpc3QuS2V5bmVzIDwtIHNlbnRlbmNlLmxpc3QgJT4lIGZpbHRlcihhdXRob3I9PSJLZXluZXMiKQplbW8ubWVhbnMuS2V5bmVzPWNvbE1lYW5zKHNlbGVjdChzZW50ZW5jZS5saXN0LktleW5lcywgYW5nZXI6cG9zaXRpdmUpPjAuMDEpCgpzZW50aW1lbnQuZGYuYnlhdXRob3IgPC0gZGF0YS5mcmFtZSgKICBncm91cD1jKCJhbmdlciIsICJhbnRpY2lwYXRpb24iLCAiZGlzZ3VzdCIsImZlYXIiLCAiam95IiwgInNhZG5lc3MiLCAic3VycHJpc2UiLCAidHJ1c3QiLCAibmVnYXRpdmUiLCAicG9zaXRpdmUiKSwKICBNYXJ4PWVtby5tZWFucy5NYXJ4LAogIExlbmluPWVtby5tZWFucy5MZW5pbiwKICBTbWl0aD1lbW8ubWVhbnMuU21pdGgsCiAgUmljYXJkbz1lbW8ubWVhbnMuUmljYXJkbywKICBLZXluZXM9ZW1vLm1lYW5zLktleW5lcwopCgpzZW50aW1lbnQuZGYuYnlhdXRob3IubG9uZyA8LSBzZW50aW1lbnQuZGYuYnlhdXRob3IgJT4lIHBpdm90X2xvbmdlcihjKCJNYXJ4IiwgIkxlbmluIiwgIlNtaXRoIiwgIlJpY2FyZG8iLCAiS2V5bmVzIiApKQoKZzQgPC0gc2VudGltZW50LmRmLmJ5YXV0aG9yLmxvbmcgJT4lIGdncGxvdChhZXMoeCA9IGdyb3VwLCB5ID0gdmFsdWUsIGZpbGwgPSBuYW1lKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKwogIGxhYnMoCiAgICB4ID0gIiIsCiAgICB5ID0gIm1lYW4gc2NvcmUgb2Ygc2VudGltZW50IiwKICAgIHRpdGxlID0gIlNlbnRpbWVudCBjb21wYXJpc29uOiBhbGwgdGhlIGF1dGhvcnMiLAogICAgc3VidGl0bGUgPSAiQ29tbXVuaXNtOiBNYXJ4LCBMZW5pbiBcbkNhcGl0YWxpc206IEtleW5lcywgUmljYXJkbywgU21pdGgiCiAgKQoKZzQKCmBgYAoKCgo=